import fetch from 'dva/fetch'
import {notification} from 'antd'
import {get} from './mapping'
import {Err} from './error'
import config from '../config/config'

const codeMessage = {
  200: '服务器成功返回请求的数据。',
  201: '新建或修改数据成功。',
  202: '一个请求已经进入后台排队（异步任务）。',
  204: '删除数据成功。',
  400: '发出的请求有错误，服务器没有进行新建或修改数据的操作。',
  401: '用户没有权限（令牌、用户名、密码错误）。',
  403: '用户得到授权，但是访问是被禁止的。',
  404: '接口不存在。',
  406: '请求的格式不可得。',
  410: '请求的资源被永久删除，且不会再得到的。',
  422: '当创建一个对象时，发生一个验证错误。',
  500: '服务器发生错误，请检查服务器。',
  502: '网关错误。',
  503: '服务不可用，服务器暂时过载或维护。',
  504: '网关超时。',
}

const checkStatus = response => {
  if (response.status >= 200 && response.status < 300) {
    return response
  }
  const errortext = codeMessage[response.status] || response.statusText
  notification.error({
    message: `请求错误 ${response.status}: ${response.url}`,
    description: errortext,
  })
  const error = new Error(errortext)
  error.name = response.status
  error.response = response
  throw error
}

/**
 * Requests a URL, returning a promise.
 *
 * @param  {string} url       The URL we want to request
 * @param  {object} [option] The options we want to pass to "fetch"
 * @return {object}           An object containing either "data" or "err"
 */
export default function request(url, option) {
  const options = {
    ...option,
  }

  const defaultOptions = {
    credentials: 'include',
  }
  const newOptions = {...defaultOptions, ...options}
  if (
    newOptions.method === 'POST' ||
    newOptions.method === 'PUT' ||
    newOptions.method === 'DELETE' ||
    newOptions.method === 'GET'
  ) {
    if (!(newOptions.body instanceof FormData)) {
      newOptions.headers = {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8',
        ...newOptions.headers,
      }
      newOptions.body = JSON.stringify(newOptions.body)
    } else {
      // newOptions.body is FormData
      newOptions.headers = {
        Accept: 'application/json',
        ...newOptions.headers,
      }
    }
  }

  return fetch(url, newOptions).then(checkStatus).then(response => {
    return new Promise(resolve => {
      response.json().then(res => {
        resolve(res)
      })
    })
  }).catch(e => {
    console.error(e)
  })
}

export const getUrl = url => {
  if (process.env.NODE_ENV === 'production') {
    return `${config.url.slice(0, -1)}${url}`
  }

  return url
}

export const getApi = async (url) => {
  return request(getUrl(url), {
    method: 'GET',
  }).then(response => {
    const code = get(response, 'code')
    if (code && code === 10000) {
      return response.data
    }

    throw new Err(response)
  })
}

export const errNotify = (err) => {
  notification.error({
    message: `错误`,
    description: Err.instance(err).getMsg(),
  })
}

export const sync = (fn, err = errNotify) => {
  return (async () => {
    return await fn()
  })().catch(e => {
    err && err(e)
  })
}
